#include <53func.h>
typedef struct node_s {
    int num;
    struct node_s * pNext;
} node_t;
typedef struct queue_s {
    node_t * pFront;
    node_t * pRear;
    int size;
} queue_t;
typedef struct shareRes_s {
    queue_t queue;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} shareRes_t;
int enQueue(queue_t *pqueue, int num){
    node_t *pNew = (node_t *)calloc(1,sizeof(node_t));// calloc pNext已经为NULL
    pNew->num = num;
    
    if(pqueue->size == 0){
        pqueue->pFront = pNew;
        pqueue->pRear = pNew;
    }
    else{
        pqueue->pRear->pNext = pNew;
        pqueue->pRear = pNew;
    }

    ++pqueue->size;
    return 0;
}
int deQueue(queue_t * pqueue){
    node_t * pCur = pqueue->pFront;
    pqueue->pFront = pCur->pNext;
    if(pqueue->size == 1){
        pqueue->pRear = NULL;
    }
    free(pCur);
    --pqueue->size;
    return 0;
}
int visitQueue(queue_t * pqueue){
    node_t *pCur = pqueue->pFront;
    while(pCur){
        printf("%4d",pCur->num); 
        pCur = pCur->pNext;
    }
    printf("\n");
    return 0;
}
// 单元测试
//int main(int argc, char *argv[])
//{
//    queue_t queue;
//    memset(&queue,0,sizeof(queue));
//    visitQueue(&queue);
//    for(int i = 0; i < 8; ++i){
//        int num = rand()%1000;
//        printf("num = %d\n", num);
//        enQueue(&queue,num);
//        visitQueue(&queue);
//    }
//    printf("-----------------\n");
//    visitQueue(&queue);
//    for(int i = 0; i < 8; ++i){
//        deQueue(&queue);
//        visitQueue(&queue);
//    }
//    return 0;
//}
//
void * producer(void *arg){
    shareRes_t * pShareRes = (shareRes_t *)arg;
    while(1){
        pthread_mutex_lock(&pShareRes->mutex);
        while(pShareRes->queue.size >= 10){
            pthread_cond_wait(&pShareRes->cond, &pShareRes->mutex);
        }
        printf("producer ready!\n");
        int num = rand()%1000;
        printf("num = %d\n", num);
        enQueue(&pShareRes->queue,num);
        printf("after produce, list = ");
        visitQueue(&pShareRes->queue);
        pthread_cond_broadcast(&pShareRes->cond);
        pthread_mutex_unlock(&pShareRes->mutex);
        sleep(3);
    }
}
void * consumer(void *arg){
    shareRes_t * pShareRes = (shareRes_t *)arg;
    sleep(5);
    while(1){
        pthread_mutex_lock(&pShareRes->mutex);
        while(pShareRes->queue.size <= 0){
            pthread_cond_wait(&pShareRes->cond, &pShareRes->mutex);
        }
        printf("consumer ready!\n");
        printf("%d is dequeue\n",pShareRes->queue.pFront->num);
        deQueue(&pShareRes->queue);
        printf("after consume, list = ");
        visitQueue(&pShareRes->queue);
        pthread_cond_broadcast(&pShareRes->cond);
        pthread_mutex_unlock(&pShareRes->mutex);
        sleep(1);
    }

}
int main(){
    shareRes_t shareRes;
    memset(&shareRes.queue,0,sizeof(shareRes.queue));
    pthread_mutex_init(&shareRes.mutex,NULL);
    pthread_cond_init(&shareRes.cond,NULL);

    for(int i = 0; i < 8; ++i){
        int num = rand()%1000;
        printf("num = %d\n", num);
        enQueue(&shareRes.queue,num);
        visitQueue(&shareRes.queue);
    }

    pthread_t producer1,producer2,producer3;
    pthread_t consumer1,consumer2;
    pthread_create(&producer1,NULL,producer,&shareRes);
    pthread_create(&producer2,NULL,producer,&shareRes);
    pthread_create(&producer3,NULL,producer,&shareRes);
    pthread_create(&consumer1,NULL,consumer,&shareRes);
    pthread_create(&consumer2,NULL,consumer,&shareRes);

    pthread_join(producer1,NULL);
    pthread_join(producer2,NULL);
    pthread_join(producer3,NULL);
    pthread_join(consumer1,NULL);
    pthread_join(consumer2,NULL);
}
